/*
 ============================================================================
 Name        : myalloc.c
 Author      : mzavatto
 Version     :
 Copyright   :
 Description : Manejo de memoria
 ============================================================================
 */

#include <stdio.h>
#include <string.h>
#include<malloc.h>
#include "myalloc.h"

void InitMem(int32_t size_in_bytes,int32_t minblock) {
	int32_t mem_aux = (size_in_bytes/minblock) * sizeof(MCB);
	int32_t total_size = size_in_bytes + mem_aux;
	/* guardo el puntero inicial y el tamaño en bytes en una varable global */
	char* pinicial = (char*) malloc(total_size);
	max_mem = total_size;
	mem_start_p = pinicial;
	mcb_count = 0;
	allocated_mem = 0;
	heap_end = mem_start_p + total_size;
}

void * myalloc(int32_t elem_size) {
	/* busco el primer bloque libre donde entre mi elemento */

	MCB_P p_mcb;
	int32_t flag = NO_MCB;
	int32_t sz;

	p_mcb = (MCB_P) mem_start_p;

	sz = sizeof(MCB);

	if ((elem_size + sz) > (max_mem - (allocated_mem + mcb_count * sz))) {
		return NULL;
	}
	while (heap_end > ((char *) p_mcb + elem_size + sz)) {

		if (p_mcb->is_available == 0) {

			if (p_mcb->size == 0) {
				flag = NEW_MCB;
				break;
			}
			if (p_mcb->size >= (elem_size + sz)) {
				flag = REUSE_MCB;
				break;
			}
		}
		//me muevo al siguiente bloque;
		p_mcb = (MCB_P) ((char *) p_mcb + p_mcb->size);

	}

	if (flag != NO_MCB) {
		p_mcb->is_available = 1;

		if (flag == NEW_MCB) {
			p_mcb->size = elem_size + sizeof(MCB);
		} else if (flag == REUSE_MCB) {
			elem_size = p_mcb->size - sizeof(MCB);
		}
		mcb_count++;
		allocated_mem += elem_size;
		return ((char *) p_mcb + sz);
	}

	return NULL;



}

void myfree(void *p) {
	/*Solo marco en mis bloques de control que esta libre */
	MCB_P ptr = (MCB_P) p;
	ptr--;

	if (ptr->is_available != FREE) {
		mcb_count--;
		ptr->is_available = FREE;
		allocated_mem -= (ptr->size - sizeof(MCB));
	}
}
